/*
 * pi_pthread.cpp
 * $Id: pi_pthread.cpp 4 2008-09-10 08:12:24Z clsung $
 */

#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <ctime>
#include "mytime.h"
#include <pthread.h>

using namespace std;
pthread_mutex_t reduction_muter;
pthread_t *tid;
double pi, w;
const int num_threads = 4;
const int interval = 100000000;

double f(double a)
{
    return (4.0 / (1.0 + a*a));
}

void *PIworker(void *arg)
{
    int myid = reinterpret_cast<unsigned long>(pthread_self()) - reinterpret_cast<unsigned long>(tid[0]);
    double sum = 0.0, mypi, x;
    for (int i = myid + 1; i <= interval; i += num_threads) {
        x = w*(static_cast<double>(i) - 0.5);
        sum += f (x);
    }
    mypi = w * sum;
    pthread_mutex_lock(&reduction_muter);
    pi += mypi;
    pthread_mutex_unlock(&reduction_muter);
    return NULL;
}

int main()
{
    clock_t s_c, e_c;
    int s_t, e_t;
    cerr << endl << "From pthread" << endl;
    cerr << "Threads   : " << num_threads << endl;
    s_t = myclock();
    s_c = clock();
    w = 1.0 / static_cast<double>(interval);
    pi = 0.0;
    tid = (pthread_t *) calloc(num_threads, sizeof(pthread_t));
    if (pthread_mutex_init(&reduction_muter, NULL)) {
        cerr << "Can not init lock" << endl; 
        return 1;
    }
    for (int i = 0; i < num_threads; ++i) {
        if (pthread_create(&tid[i], NULL, PIworker, NULL)) {
            cerr << "Can not create thread " << tid[i] << endl;
            return 1;
        }
    }
    for (int i = 0; i < num_threads; ++i)
        pthread_join(tid[i], NULL);
    e_t = myclock();
    e_c = clock();
    cerr << "pi = " << fixed << pi << endl;
    cerr << "cost " << (static_cast<double>(e_c - s_c) / CLOCKS_PER_SEC ) << " Sec." << endl;
    cerr << "cost " << (static_cast<double>(e_t - s_t) / 1000000) << " Sec." << endl;
    return 0;
}
